<?php

namespace app\common\util;

use app\common\model\setting\ConfigWeb;
use app\common\model\setting\TraceIDSetting;
use think\facade\Cache;
use think\Model;
use function MongoDB\BSON\toJSON;

/**
 * 通用返回值
 */
class Result
{
    const CODE_SUCCESS = 0;

    /**
     * $code 业务码
     *
     * @var mixed
     */
    protected $code = -1;

    /**
     * $data 数据
     *
     * @var mixed
     */
    protected $data;

    /**
     * $msg 提示消息
     *
     * @var string
     */
    protected $msg = 'Never init error';

    protected $trace_id;

    /**
     * 接口版本号，如果接口版本号低于小程序版本号，说明是审核中，否则就是审核通过了
     * @var int
     */
    protected $version_code = 2;

    public function __construct($data, $code = 0, $msg = '')
    {
        $this->code = $code;
        $this->data = $data;
        $this->msg = $msg;

        $this->trace_id = TraceIDSetting::instance()->getTraceID();
        $this->version_code = ConfigWeb::instance()->version_code;

    }

    /**
     * 判断是否出错，true为失败，false为成功
     * @return bool
     */
    public function isError(): bool
    {
        return !$this->isSuccess();
    }

    /**
     * 判断是否成功，true为成功，false为失败
     * @return bool
     */
    public function isSuccess(): bool
    {
        if ($this->code == self::CODE_SUCCESS) {
            return true;
        }
        return false;
    }

    public static function of($data, $code = 0, $msg = '成功'): Result
    {
        return new Result($data, $code, $msg);
    }

    public static function success($data = null, $msg = "成功"): Result
    {
        return new Result($data, 0, $msg);
    }

    public static function simpleFailed($msg, $code = 999, $data = null): Result
    {
        return self::failed($code, $msg, $data);
    }

    public static function error($msg, $code = 999, $data = null): Result
    {
        return self::failed($code, $msg, $data);
    }

    public static function failed($code, $msg, $data = null): Result
    {
        return new Result($data, $code, $msg);
    }

    public function toJson(): \think\response\Json
    {
        return json($this->toArray());
    }

    public function toArray(): array
    {
        return [
            'trace_id' => $this->trace_id,
            'code' => $this->code,
            'msg' => $this->msg ? $this->msg : '错误',
            'data' => $this->data,
            'version_code' => $this->version_code,
        ];
    }


    /**
     * 生成 Http Json Result 数据
     *
     * @param mixed $data
     * @param int $code
     * @param string $msg
     *
     * @return \think\Response\Json
     */
    public static function rest($data = null, $code = 0, $msg = '成功'): \think\Response\Json
    {

        return (new Result($data, $code, $msg))->toJSON();//json(["data" => $data, "code" => $code, "msg" => $msg, 'trace_id'=>$this->trace_id]);
    }

    /**
     * 生成 Http Json Result 失败的数据
     *
     * @param int $code
     * @param string $msg
     *
     * @return \think\Response\Json
     */
    public static function restf(int $code, string $msg): \think\Response\Json
    {
        return self::rest(null, $code, $msg);
    }

    /**
     * 返回json
     * @param array $res
     * @return \think\Response\Json
     */
    public static function json(array $res): \think\Response\Json
    {
        return self::rest($res["data"], $res["code"], $res["msg"]);
    }

    /**
     * 参数是Result的返回值，直接返回json
     * @param Result $result
     * @return \think\Response\Json
     */
    public static function jsonByResult(Result $result): \think\Response\Json
    {
        return self::rest($result->getData(), $result->getCode(), $result->getMsg());
    }

    /**
     * @return int|mixed
     */
    public function getCode(): mixed
    {
        return $this->code;
    }

    /**
     * @param int|mixed $code
     */
    public function setCode(mixed $code): void
    {
        $this->code = $code;
    }

    public function getData(): mixed
    {
        return $this->data;
    }

    public function setData(mixed $data): void
    {
        $this->data = $data;
    }

    /**
     * @return mixed|string
     */
    public function getMsg(): mixed
    {
        return $this->msg;
    }

    /**
     * @param mixed|string $msg
     */
    public function setMsg(mixed $msg): void
    {
        $this->msg = $msg;
    }
}
